/*
 * 文件名： ScanPayPabManager.java
 * 
 * 工程名称: bis-manager
 *
 * Gopay
 *
 * 创建日期： 2017年8月11日
 *
 * Copyright(C) 2017, by www.gopay.com.cn Inc.All rights reserved.
 *
 * 原始作者: 宣广海
 *
 */
package com.gopay.bis.manager.bank.scan;

import java.math.BigDecimal;
import java.security.MessageDigest;
import java.util.Date;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.PabConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.cps.dao.aggregatepayment.ApContractInfoQueryDAO;
import com.gopay.common.domain.aggregatepayment.ApContractInfo;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.ScanPayBaseMessage;
import com.gopay.common.domain.bank.pab.agpay.req.BillDownloadMsg;
import com.gopay.common.domain.bank.pab.agpay.req.MerchantAddMsg;
import com.gopay.common.domain.bank.pab.agpay.req.MerchantAddPaymentMsg;
import com.gopay.common.domain.bank.pab.agpay.req.MerchantAddPaymentTypeMsg;
import com.gopay.common.domain.bank.pab.agpay.req.MerchantConfig;
import com.gopay.common.domain.bank.pab.agpay.req.PayOrderMsg;
import com.gopay.common.domain.bank.pab.agpay.req.PayRefundMsg;
import com.gopay.common.domain.bank.pab.agpay.req.PayRefundQueryMsg;
import com.gopay.common.domain.bank.pab.agpay.req.PayStatusMsg;
import com.gopay.common.domain.bank.pab.agpay.res.MerchantAddResMsg;
import com.gopay.common.domain.bank.wechat.scan.cmbc.FileDownReq;
import com.gopay.common.domain.bank.wechat.scan.cmbc.MerchantOperation;
import com.gopay.common.domain.bank.wechat.scan.cmbc.MerchantSettled;
import com.gopay.common.domain.cust.CustSettledInfo;
import com.gopay.common.exception.GopayException;
import com.gopay.common.user.dao.CustSettledInfoDao;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.FastJsonUtil;
import com.gopay.common.util.TransUtil;
import com.gopay.remote.bank.businesses.PabScanPayService;

/**
 * 扫码支付平安银行渠道报文拼装处理
 *
 * @author 宣广海
 *
 * @version
 *
 * @since 2017年8月11日
 */
public class ScanPayPabManager {
	/**
	 * 日志对象
	 */
	private static Logger logger = LoggerFactory.getLogger(ScanPayPabManager.class);

	@Resource(name = "aPayPabServiceClient")
	private PabScanPayService aPayPabServiceClient;
	@Resource(name = "aPayPabConfig")
	private Map<String, String> aPayPabConfig;
	@Resource(name = "custSettledInfoDao")
	private CustSettledInfoDao custSettledInfoDao;
	@Resource(name = "apContractInfoQueryDAO")
	private ApContractInfoQueryDAO apContractInfoQueryDAO;

	/**
	 * 
	 * 功能描述：微信扫码、支付宝扫码平安银行上送报文构建
	 *
	 * @param msg
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年8月11日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object scanPay(BaseMessage msg) throws GopayException {
		msg.setBankOrderId(modifyOrderId(msg.getOrderId()));
		ScanPayBaseMessage scanPayBase = (ScanPayBaseMessage) msg;
		try {
			/**
			 * 获取商户入驻编号需要修改获取方法加入渠道概念,需要设置商户进件成功后返回的密钥。
			 */
			CustSettledInfo info = getCustSettledsInfo(msg.getCustomerID(), msg.getOutStlmCd(),
					msg.getBankIntrChann().value);
			
			if (null == info) {
				logger.info(msg.getCustomerID() + ",此商户没有找到入驻帐号！");
				throw new GopayException(ProcCodeConstants.PROC_CODE_100E1165);
			}			
			PayOrderMsg payOrder = new PayOrderMsg();
			if (BankConstants.BANK_LOGO_ALIPAY.equals(msg.getOutStlmCd())) {
				/**
				 * 判断不是自动续签的合同是否到期，到期的合同不能正常做交易
				 */
				if (getContrantInfo(msg.getCustomerID(), PabConstants.CONTRACT_AUTOSIGN_OFF,
						PabConstants.CONTRACT_STATUS_AUDIT_SUCCESS, PabConstants.CONTRACT_ALIPAY)) {
					throw new GopayException(ProcCodeConstants.PROC_CODE_100E1216);
				}
				payOrder.setPmt_tag(aPayPabConfig.get("ALIPAY.PMT_TAG"));
				// 不支持信用卡
				payOrder.setLimit_pay("no_credit");
				payOrder.setGoods_detail(null);
				payOrder.setExtend_params(null);
			}
			if (BankConstants.BANK_LOGO_WECHAT.equals(msg.getOutStlmCd())) {
				/**
				 * 判断不是自动续签的合同是否到期，到期的合同不能正常做交易
				 */
				if (getContrantInfo(msg.getCustomerID(), PabConstants.CONTRACT_AUTOSIGN_OFF,
						PabConstants.CONTRACT_STATUS_AUDIT_SUCCESS, PabConstants.CONTRACT_WECHAT)) {
					throw new GopayException(ProcCodeConstants.PROC_CODE_100E1217);
				}
				payOrder.setPmt_tag(aPayPabConfig.get("WECHAT.PMT_TAG"));
				payOrder.setGoods_tag(null);
				// 1-限定不能使用信用卡支付，传空是使用信用卡
				if ("0".equals(scanPayBase.getLimitCreditPay())) {
					payOrder.setLimit_pay("");
				} else {
					payOrder.setLimit_pay("no_credit");
				}
			}
			payOrder.setOut_no(msg.getBankOrderId());
			payOrder.setPmt_name(null);
			payOrder.setOrd_name(scanPayBase.getGoodsBody());
			/**
			 * 原始交易金额，精确到分
			 */
			payOrder.setOriginal_amount(
					new BigDecimal(TransUtil.amountConvert2Fen(String.valueOf(scanPayBase.getAmount()))));
			payOrder.setDiscount_amount(null);
			payOrder.setIgnore_amount(null);
			payOrder.setTrade_amount(
					new BigDecimal(TransUtil.amountConvert2Fen(String.valueOf(scanPayBase.getAmount()))));
			payOrder.setTrade_account(null);
			payOrder.setTrade_no(null);
			payOrder.setRemark(null);
			payOrder.setTag(null);
			payOrder.setNotify_url(scanPayBase.getPayRuturnUrl());
			payOrder.setAuth_code(null);
			payOrder.setJump_url(null);
			// 从商户入驻表中获取key
			scanPayBase.setMerID(info.getBankMerchantCode());
			// 从商户入驻表中获取key
			scanPayBase.setMchKey(info.getPayKey());
			
//			scanPayBase.setMerID(msg.getMerID());
//			scanPayBase.setMchKey(msg.getPrivateKeyPath());
			scanPayBase.setPlainMessage(buildSignPlain(payOrder));
			logger.info("info.getPayKey()" + info.getPayKey());
			logger.info("pab build datajson= :" + buildSignPlain(payOrder));
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7025, e);
		}
		return aPayPabServiceClient.payment(scanPayBase);
	}

	/**
	 * 
	 * 功能描述：平安渠道订单查询报文
	 *
	 * @param msg
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年8月16日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object orderQuery(BaseMessage msg) throws GopayException {
		ScanPayBaseMessage scanPayBase = (ScanPayBaseMessage) msg;
		try {
			CustSettledInfo info = getCustSettledsInfo(msg.getCustomerID(), msg.getOutStlmCd(),
					msg.getBankIntrChann().value);
			if (null == info) {
				logger.info(msg.getCustomerID() + ",此商户没有找到入驻帐号！");
				throw new GopayException(ProcCodeConstants.PROC_CODE_100E1165);
			}
			/**
			 * 准备构建报文体对象
			 */
			PayStatusMsg payOrder = new PayStatusMsg();
			payOrder.setOrd_no("");
			 if(BisBankBusinessProd._26.value.equals(msg.getBankBusProd().value)){
				 payOrder.setOut_no(msg.getCzOriBankOrderId());
	            }
			 else{
				 payOrder.setOut_no(msg.getBankOrderId());
			 }
			scanPayBase.setMerID(info.getBankMerchantCode());
			scanPayBase.setMchKey(info.getPayKey());
//			scanPayBase.setMerID(msg.getMerID());
//			scanPayBase.setMchKey(msg.getPrivateKeyPath());
			scanPayBase.setPlainMessage(buildSignPlain(payOrder));
			logger.info("pab query manager orderQuery message :" + buildSignPlain(payOrder));
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6063, e);
		}
		return aPayPabServiceClient.queryOrder(scanPayBase);
	}

	/**
	 * 
	 * 功能描述：平安渠道订单退款报文
	 *
	 * @param msg
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年8月16日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object refund(BaseMessage msg) throws GopayException {
		msg.setBankOrderId(modifyOrderId(msg.getOrderId()));
		ScanPayBaseMessage scanPayBase = (ScanPayBaseMessage) msg;
		try {
			/**
			 * 退款签名验签用机构公用的
			 */
			CustSettledInfo info = getCustSettledsInfo(msg.getCustomerID(), msg.getOutStlmCd(),
					msg.getBankIntrChann().value);
			if (null == info) {
				logger.info(msg.getCustomerID() + ",此商户没有找到入驻帐号！");
				throw new GopayException(ProcCodeConstants.PROC_CODE_100E1165);
			}
			/**
			 * 准备构建报文体对象
			 */
			PayRefundMsg payRefundMsg = new PayRefundMsg();
			// 原始订单的开发者交易流水号
			payRefundMsg.setOut_no(msg.getTkOriBankOrderId());
			payRefundMsg.setRefund_out_no(msg.getBankOrderId());
			payRefundMsg.setRefund_ord_name(null);
			payRefundMsg.setRefund_amount(new BigDecimal(TransUtil.amountConvert2Fen(String.valueOf(msg.getAmount()))));
			payRefundMsg.setTrade_account(null);
			payRefundMsg.setTrade_no(null);
			payRefundMsg.setTrade_result(null);
			payRefundMsg.setTml_token(null);
			payRefundMsg.setRemark(null);
			// 默认为123456
			payRefundMsg.setShop_pass(methodSHA1("123456"));

			scanPayBase.setMerID(info.getBankMerchantCode());
			scanPayBase.setMchKey(info.getPayKey());
//			scanPayBase.setMerID(msg.getMerID());
//			scanPayBase.setMchKey(msg.getPrivateKeyPath());
			scanPayBase.setPlainMessage(buildSignPlain(payRefundMsg));
			logger.info("pab refund manager  message :" + buildSignPlain(payRefundMsg));
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E1163, e);
		}
		return aPayPabServiceClient.refund(scanPayBase);
	}
	/**
	 * 
	 * 功能描述：平安渠道退款订单查询报文
	 *
	 * @param msg
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年8月16日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object refundOrderQuery(BaseMessage msg) throws GopayException {
		ScanPayBaseMessage scanPayBase = (ScanPayBaseMessage) msg;
		try {
			CustSettledInfo info = getCustSettledsInfo(msg.getCustomerID(), msg.getOutStlmCd(),
					msg.getBankIntrChann().value);
			if (null == info) {
				logger.info(msg.getCustomerID() + ",此商户没有找到入驻帐号！");
				throw new GopayException(ProcCodeConstants.PROC_CODE_100E1165);
			}
			/**
			 * 准备构建报文体对象
			 */
			PayRefundQueryMsg payRefundOrder = new PayRefundQueryMsg();
			payRefundOrder.setRefund_ord_no(null);
			payRefundOrder.setRefund_out_no(msg.getBankOrderId());

			scanPayBase.setMerID(info.getBankMerchantCode());
			scanPayBase.setMchKey(info.getPayKey());
//			scanPayBase.setMerID(msg.getMerID());
//			scanPayBase.setMchKey(msg.getPrivateKeyPath());
			scanPayBase.setPlainMessage(buildSignPlain(payRefundOrder));
			logger.info("pab refund query manager orderQuery message :" + buildSignPlain(payRefundOrder));
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6063, e);
		}
		return aPayPabServiceClient.refundQuery(scanPayBase);
	}
	/**
	 * 
	 * 功能描述：异步通知验签
	 *
	 * @param msg
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年8月17日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object verify(BaseMessage msg) throws GopayException {
		boolean falg = false;
		/**
		 * 退款签名验签用机构公用的
		 */
		CustSettledInfo info = getCustSettledsInfo(msg.getCustomerID(), msg.getOutStlmCd(),
				msg.getBankIntrChann().value);
		if (null == info) {
			logger.info(msg.getCustomerID() + ",此商户没有找到入驻帐号！");
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E1165);
		}
		try {
			logger.info("pab  manager verify message :" + ToStringBuilder.reflectionToString(msg));
			msg.setMchKey(info.getPayKey());
//			msg.setMchKey(msg.getPrivateKeyPath());
			falg = (boolean) aPayPabServiceClient.verify(msg);
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026, e);
		}
		return falg;
	}
	/**
	 * 
	 * 功能描述：商户入驻报文构建
	 *
	 * @param msg
	 * @param param
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年8月22日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object merchantSettled(MerchantSettled msg, Map<String,String> param)
			throws GopayException {
		ScanPayBaseMessage scanPayBase = new ScanPayBaseMessage();
		try {
			MerchantAddMsg merchantAddMsg = new MerchantAddMsg();
			MerchantAddPaymentMsg payment=new MerchantAddPaymentMsg();

			
			merchantAddMsg.setTra_id(msg.getMerchantId());
			merchantAddMsg.setMct_name(msg.getMerchantName());
			//企业简称
			merchantAddMsg.setBrand_name(msg.getCorpShortName());
			merchantAddMsg.setMobile(msg.getServicePhone());
			merchantAddMsg.setTel(msg.getServicePhone());
			merchantAddMsg.setContract_name(msg.getContactName());
			merchantAddMsg.setEmail(msg.getContactEmail());
			merchantAddMsg.setCityid(msg.getDistrictCode());
			merchantAddMsg.setAddress(msg.getMerchantAddress());
			//9:00-12:00,13:00-18:00
			merchantAddMsg.setOpen_hours("00:00-23:59");
			if("WXZF".equals(msg.getPayWay())){
				MerchantAddPaymentTypeMsg wechat=new MerchantAddPaymentTypeMsg();
				wechat.setCategory(PabConstants.WX_CATEGORY);
				wechat.setFee(PabConstants.WX_FREE);
				payment.setWeixinBERL(wechat);
				/**
				 * 生产环境
				 */
//				payment.setWeixin(wechat);
			}
			if("ZFBZF".equals(msg.getPayWay())){
				MerchantAddPaymentTypeMsg alipay=new MerchantAddPaymentTypeMsg();
				alipay.setCategory(PabConstants.ZFB_CATEGORY);
				alipay.setFee(PabConstants.ZFB_FREE);
				payment.setAlipayCS(alipay);
				/**
				 * 生产环境
				 */
				//payment.setAlipayPAZH(alipay);
			}
																
			merchantAddMsg.setPayment(payment);
					
			scanPayBase.setMerID(param.get("merId"));
			scanPayBase.setMchKey(param.get("merKey"));

			scanPayBase.setPlainMessage(buildSignPlain(merchantAddMsg));
			scanPayBase.setPayUrl(aPayPabConfig.get("PAB_MERCHANT_SETTLED_URL"));
			logger.info("pab merchantSettled add build datajson= :" + buildSignPlain(merchantAddMsg));
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7025, e);
		}
		return aPayPabServiceClient.merchantSettled(scanPayBase);
	}
	/**
	 * 
	 * 功能描述：
	 *
	 * @param msg
	 * @param param
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年8月23日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object merchantOperation(MerchantOperation msg, Map<String,String> param)
			throws GopayException {
		ScanPayBaseMessage scanPayBase = new ScanPayBaseMessage();
		try {
			MerchantConfig merchantConfig = new MerchantConfig();
			
			merchantConfig.setCtt_code(msg.getCtt_code());
			
			if("5".equals(msg.getZdlx())){
				merchantConfig.setJsapi_path(msg.getJsapi_path());
			}
			if("6".equals(msg.getZdlx())){
				merchantConfig.setSub_appid(msg.getSub_appid());
			}
			if("7".equals(msg.getZdlx())){
				merchantConfig.setSubscribe_appid(msg.getSubscribe_appid());
			}
			scanPayBase.setMerID(param.get("merId"));
			scanPayBase.setMchKey(param.get("merKey"));

			scanPayBase.setPlainMessage(buildSignPlain(merchantConfig));
			scanPayBase.setPayUrl(aPayPabConfig.get("PAB_MERCHANT_SETTLED_URL"));
			logger.info("pab merchantConfig add build datajson= :" + buildSignPlain(merchantConfig));
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7025, e);
		}
		return aPayPabServiceClient.merchantOperation(scanPayBase);
	}
	/**
	 * 
	 * 功能描述：下载对账文件报文构建
	 *
	 * @param fileReq
	 * @param param
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年8月22日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object getCheckAccountFile(FileDownReq fileReq,Map<String,String> param)
			throws GopayException {
		ScanPayBaseMessage scanPayBase = new ScanPayBaseMessage();
		try {
			BillDownloadMsg billDownloadMsg = new BillDownloadMsg();
			billDownloadMsg.setDay(fileReq.getDate());
			billDownloadMsg.setTar_type("gzip");
							
			scanPayBase.setMerID(param.get("merId"));
			scanPayBase.setMchKey(param.get("merKey"));
//			scanPayBase.setPrivateKeyPath(param.get("privateKeyPath"));
//			scanPayBase.setPublicKeyPath(param.get("publicKeyPath"));
			scanPayBase.setPlainMessage(buildSignPlain(billDownloadMsg));
			scanPayBase.setPayUrl(aPayPabConfig.get("PAB_MERCHANT_SETTLED_URL"));
			scanPayBase.setBankOrderType(billDownloadMsg.getTar_type());
			logger.info("pab merchantSettled add build datajson= :" + buildSignPlain(billDownloadMsg));
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7025, e);
		}
		return aPayPabServiceClient.getCheckAccountFile(scanPayBase);
	}
	public String buildSignPlain(Object obj) {
		return FastJsonUtil.toJSONString(obj);
	}

	private static String modifyOrderId(String orderId) {
		return "PA" + orderId.substring(2);
	}

	private CustSettledInfo getCustSettledsInfo(String custId, String bank, String inchCode) {
		CustSettledInfo info = null;
		if (BankConstants.BANK_LOGO_WECHAT.equals(bank)) {
			info = custSettledInfoDao.getCustSettledInfoByCustIdAndChannel(custId, PabConstants.WECHAT_SETTLED, inchCode);
		}
		if (BankConstants.BANK_LOGO_ALIPAY.equals(bank)) {
			info = custSettledInfoDao.getCustSettledInfoByCustIdAndChannel(custId, PabConstants.ZFB_SETTLED,
					inchCode);
		}
		return info;
	}
	private boolean getContrantInfo(String custId, String autoSingh, String status, String type) {
		String endDate = DateUtils.format(new Date(), DateUtils.yyyy_MM_dd);
		logger.error("到期时间：endDate={}", endDate);
		ApContractInfo query = new ApContractInfo();
		query.setAutoSign(autoSingh);
		query.setStatus(status);
		query.setCustId(custId);
		query.setType(type);
		query.setEdate(endDate);
		// 查询出自动续约、第二天到期、状态为已审核的商户合同
		ApContractInfo apContractInfo = apContractInfoQueryDAO.getApContractInfo(query);
		if (null != apContractInfo) {
			logger.error("合同已经过期：custId={},corpName={}", apContractInfo.getCustId(), apContractInfo.getCustName());
			return true;
		}
		return false;
	}
	private String methodSHA1(String decript) {
		try {
			MessageDigest digest = MessageDigest.getInstance("SHA-1");
			digest.update(decript.getBytes("UTF-8"));
			byte[] messageDigest = digest.digest();
			StringBuilder hexString = new StringBuilder();
			for (byte message : messageDigest) {
				String shaHex = Integer.toHexString(message & 0xFF);
				if (shaHex.length() < 2) {
                    hexString.append(0);
                }
				hexString.append(shaHex);
			}
			return hexString.toString().toLowerCase();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}
	public static void main(String[]args){
		String json="{"+
		       " 'mct_no': '1234567890',"
		       +"  'tra_id': '12345678',"
		       +"  'open_id': 'e10adc3949ba59abbe56e057f20f883e',"
		       +"  'open_key': '25d55ad283aa400af464c76d713c07ad',"
		       +"  'payment': {"
		        +"     'WeixinBERL': {"
		        +"         'category': '203',"
		       +"         'fee': '0.3',"
		         +"        'mch_id': '12345'"
		         +"     },"
		         +"    'AlipayPAZH': {"
		         +"        'category': '2015050700000010',"
		         +"        'fee': '0.3',"
		         +"       'mch_id': '12345'"
		         +"    }"
		         +" }"
		         +" }";

		MerchantAddResMsg merchantResMsg = FastJsonUtil.toBean(json, MerchantAddResMsg.class);
		System.out.println(merchantResMsg.getOpen_key());	
	}
}
